﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace ChipSharp
{
    class Renderer
    {
        private int myHoriEdges = 4;
        private int myMenuHeight = 24;
        private int myMaxMargin = 36;

        private ContainerControl myForm = null;
        private Bitmap myDrawArea = null;

        private World myWorld = null;
        private Bitmap myWorldArea = null;
        private Mutex myWorldAreaMutex = new Mutex(false);
        private Rectangle myWorldRect = new Rectangle();

        private Panel myPanel = null;
        private Bitmap myPanelArea = null;
        private Rectangle myPanelRect = new Rectangle();

        public Bitmap WorldArea
        {
            get
            {
                return myWorldArea;
            }
        }

        public Mutex WorldAreaMutex
        {
            get
            {
                return myWorldAreaMutex;
            }
        }

        public Bitmap PanelArea
        {
            get
            {
                return myPanelArea;
            }
        }

        public World World
        {
            get { return myWorld; }
            set { myWorld = value; }
        }

        public Panel Panel
        {
            get { return myPanel; }
            set { myPanel = value; }
        }

        public Renderer(ContainerControl form, int width, int height)
        {
            myForm = form;
            myDrawArea = new Bitmap(width, height,
                System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            Rearrange();
        }

        /* for Form */
        public void Resize(int width, int height)
        {
            myDrawArea = new Bitmap(width, height, 
                System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            Rearrange();
        }

        public void Rearrange()
        {
            int width = myDrawArea.Width - myHoriEdges;
            int height = myDrawArea.Height;
            int visibleHeight = height - myMenuHeight;

            int sideLen = Func<int>.Min(width, visibleHeight);

            int margin = sideLen / 10;
            if (margin > myMaxMargin) margin = myMaxMargin;
            sideLen -= margin * 2;

            myWorldRect = new Rectangle(margin, margin + myMenuHeight, sideLen, sideLen);
            myWorldArea = new Bitmap(sideLen, sideLen);

            if ( (width - (margin * 2 + sideLen)) * 3 >= sideLen )
            {
                int panelWidth = width - margin * 2 - sideLen;
                int panelHeight = sideLen;
                myPanelRect = new Rectangle(margin + sideLen, margin + myMenuHeight, panelWidth, panelHeight);
                myPanelArea = new Bitmap(panelWidth, panelHeight);
            }
            else if ((height - (myMenuHeight + margin * 2 + sideLen)) * 3 >= sideLen)
            {
                int panelWidth = sideLen;
                int panelHeight = height - margin * 2 - myMenuHeight - sideLen;
                myPanelRect = new Rectangle(margin, margin + myMenuHeight + sideLen, panelWidth, panelHeight);
                myPanelArea = new Bitmap(panelWidth, panelHeight);
            }
            else
            {
                myPanelArea = null;
            }
        }

        public void Render(PaintEventArgs e)
        {
            Graphics graph = e.Graphics;
            Graphics graphForm = Graphics.FromImage(myDrawArea);

            if (myPanel != null && myPanelArea != null)
            {
                myPanel.Draw();
                graphForm.DrawImage(myPanelArea, myPanelRect);
            }
            else
            {
                graphForm.Clear(Color.Black);
            }

            try
            {
                myWorldAreaMutex.WaitOne();
                graphForm.DrawImage(myWorldArea, myWorldRect);
            }
            finally
            {
                myWorldAreaMutex.ReleaseMutex();
            }

            graph.DrawImage(myDrawArea, 0, 0);
        }

        public void Invalidate()
        {
            myForm.Invalidate();
        }
    }
}
